const Service = require('egg').Service;
const _ = require('lodash');
const moment = require('moment');
const safeEval = require('safe-eval');
const parallel = require('async/parallel');


class XiaohuluService extends Service {
    // 默认不需要提供构造函数。
    // constructor(ctx) {
    //     super(ctx);
    //     /*    如果需要在构造函数做一些处理，一定要有这句话，才能保证后面 `this.ctx`的使用。
    //         就可以直接通过 this.ctx 获取 ctx 了
    //         还可以直接通过 this.app 获取 app 了*/
    // }

    /**
     * 抓取主播的小葫芦ID
     * @param anchor
     * @param range 数据长度范围,7=7天，30=30天
     * @returns {Promise<void>}
     */
    async get(anchor, range = 7) {
        const ctx = this.ctx;
        const {Platform, DetailAnchorData} = this.app.model;

        let platform = anchor.platform;
        if (_.isEmpty(anchor._id))
            throw new Error('主播没有小葫芦ID');
        if (_.isEmpty(platform)) {
            if (_.isEmpty(anchor.platform_id))
                throw new Error('没有平台数据');
            platform = Platform.findByPk(anchor.platform_id);
        }

        if (_.isEmpty(platform.type))
            throw new Error('平台没有小葫芦ID');

        let url = Url(platform.type, anchor._id);

        let res = await ctx.curl(url);
        res = await parseHTML(range, anchor, res.data.toString());
        DetailAnchorData.bulkCreate(res, {updateOnDuplicate: ['gift', 'gift1', 'fans', 'watch', 'time', 'danmu', 'danmu1']});
    }
}

module.exports = XiaohuluService;


/**
 *
 * @param platform
 * @param anchorRoomId
 * @returns {string}
 * @function
 */
function Url(platform, anchorRoomId) {
    return `http://xiaohulu.com/anchor2/details.html?plat=${platform}&roomid=${anchorRoomId}`;
}

/**
 *
 * @param range
 * @param anchor
 * @param html
 * @returns {Promise<any>}
 */
async function parseHTML(range, anchor, html) {
    let code = html.match(new RegExp(/settimeline\s+=\s+(function.+return obj;\s+})/, 'sim'));
    let yesterday = moment().subtract(1, 'day');
    let tempData = {}, fun = safeEval(code[1]);

    let command;
    if (range === 7) {
        command = [
            {case: 3, key: 'gift1'},
            {case: 4, key: 'gift'},
            {case: 5, key: 'danmu'},
            {case: 6, key: 'danmu1'},
            {case: 7, key: 'fans'},
            {case: 8, key: 'watch'},
            {case: 9, key: 'time'},];
    } else {
        command = [
            {case: 10, key: 'gift1'},
            {case: 11, key: 'gift'},
            {case: 12, key: 'danmu'},
            {case: 13, key: 'danmu1'},
            {case: 14, key: 'fans'},
            {case: 15, key: 'watch'},
            {case: 16, key: 'time'},];
    }

    return new Promise(resolve => {
        parallel(command.map(item => {
                return callback => {
                    let data = fun(item.case);//{timestr:[], data:[]}
                    tempData[item.key] = data.data;
                    callback();
                };
            }),
            () => {
                let finalData = [];
                let length = tempData['fans'].length;
                for (let i = length - 1; i >= 0; i--) {
                    let created_at = yesterday.format('YYYY-MM-DD'),
                        fans = tempData['fans'][i],
                        gift = tempData['gift'][i],
                        gift1 = tempData['gift1'][i],
                        danmu = tempData['danmu'][i],
                        danmu1 = tempData['danmu1'][i],
                        watch = tempData['watch'][i],
                        time = tempData['time'][i];
                    finalData.splice(0, 0, {
                        anchor_id: anchor.id,
                        created_at,
                        fans,
                        watch,
                        gift,
                        gift1,
                        time,
                        danmu,
                        danmu1
                    });
                    yesterday.subtract(1, 'day');
                }
                resolve(finalData);
            });
    });
}